package cn.devcat.sso.service.impl;

import cn.devcat.sso.entity.*;
import cn.devcat.sso.enums.ViewTypeEnum;
import cn.devcat.sso.mapper.DevcatNoteMapper;
import cn.devcat.sso.service.*;
import cn.devcat.sso.util.PageHelperUtil;
import cn.devcat.sso.util.UserUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class DevcatNoteServiceImpl extends ServiceImpl<DevcatNoteMapper, DevcatNote> implements IDevcatNoteService {

  @Autowired
  UserUtil userUtil;
  @Autowired
  INoteTextService textService;

  @Autowired
  IBlogCommentService blogCommentService;

  @Resource
  DevcatNoteMapper noteMapper;

  @Autowired
  INoteTagService tagService;

  @Autowired
  IDevcatRoleService roleService;

  @Override
  public Long addNote(DevcatNote note) {
    checkNOteParam(note);
    note.setCreateTime(LocalDateTime.now());
    note.setUpdateTime(LocalDateTime.now());
    note.setViewType(note.getViewType());
    if (StringUtils.isEmpty(note.getNoteType())) {
      note.setNoteType("md");
    }
    String userId = userUtil.getUserByRequest().getId();
    note.setUserId(userId);
    save(note);
    NoteText noteText = new NoteText();
    noteText.setId(note.getId());
    noteText.setContent(note.getNoteTitle());
    textService.addNoteText(noteText);
    if(note.getNoteTagList() != null && !note.getNoteTagList().isEmpty()){
      tagService.bindTagRelation(note.getId(), note.getNoteTagList());
    }
    return note.getId();
  }

  @Override
  public void delNote(List<Long> ids, boolean isAdmin) {
    String id = userUtil.getUserByRequest().getId();
    List<DevcatNote> devcatNotes = listByIds(ids);
    if(!isAdmin){
      long count = devcatNotes.stream().map(DevcatNote::getUserId).filter(item -> !item.equals(id)).count();
      if(count > 0){
        throw new RuntimeException("您当前的权限无法删除不是你的笔记内容");
      }
    }
    removeByIds(ids);
    textService.removeByIds(ids);
    tagService.unbindTagRelation(ids,"note");
  }

  @Transactional
  @Override
  public void setNote(DevcatNote note) {
//    checkNOteParam(note);
    note.setUpdateTime(LocalDateTime.now());
    updateById(note);
    if(note.getNoteTagList() != null && !note.getNoteTagList().isEmpty()){
      tagService.bindTagRelation(note.getId(), note.getNoteTagList());
    }
  }

  @Override
  public void changeViewType(DevcatNote note) {
    if (ViewTypeEnum.typeEnum(note.getViewType()) == ViewTypeEnum.ABOUT) {
      String id = userUtil.getUserByRequest().getId();
      List<DevcatRole> roleListByUserId = roleService.getRoleListByUserId(id);
      long count = roleListByUserId.stream().filter(item -> item.getRoleCode().equals("ROLE_ADMIN")).count();
      if(count == 0){
        throw new RuntimeException("抱歉，该功能只有管理员可以使用");
      }
//      String roleName = SecurityContextHolder.getContext().getAuthentication().getName();
      DevcatNote one = getOne(new QueryWrapper<DevcatNote>().select("id").eq("view_type", ViewTypeEnum.ABOUT.getType()));
      if (one != null) {
        update(new UpdateWrapper<DevcatNote>().eq("id", one.getId()).set("view_type", "private"));
      }
    }
    updateById(note);
  }

  @Override
  public PageData<DevcatNote> getNotePageData(SearchCommonParam param) {
    String userId = userUtil.getUserByRequest().getId();
    PageHelperUtil.handle(param);
    List<DevcatNote> list = noteMapper.getDevcatNoteList(param, userId);
    list.forEach(item->item.setNoteTagList(tagService.getTagListByNoteId(item.getId())));
    return PageHelperUtil.makePageData(new PageInfo<>(list));
  }

  @Override
  public PageData<DevcatNote> getPublicNotePageData(SearchCommonParam param) {
    if(param.getPageNum()==null || param.getPageNum() == 0){
      param.setPageNum(1);
    }
    param.setPageSize(10);
    PageHelperUtil.handle(param);
    param.setNoteStatus("public");
    List<DevcatNote> list = noteMapper.getDevcatNoteList(param, null);
    List<BlogComment> commentList = blogCommentService.list();
    Map<Long, List<BlogComment>> commentMap = commentList.stream().collect(Collectors.groupingBy(BlogComment::getNoteId));
    list.forEach(item->item.setNoteTagList(tagService.getTagListByNoteId(item.getId())));
    list.forEach(item->item.setCommentCount(commentMap.get(item.getId()) == null ? 0 : commentMap.get(item.getId()).size()));
    if (StringUtils.isNotEmpty(param.getKeyword())) {
      list.forEach(item -> {
        item.setNoteTitle(highlight2(item.getNoteTitle(), param.getKeyword()));
        item.setNoteDescribe(highlight2(item.getNoteDescribe(), param.getKeyword()));
      });
    }
    return PageHelperUtil.makePageData(new PageInfo<>(list));
  }

  public String highlight2(String content, String keyword) {
    if (content == null) {
      return "";
    }
    StringBuilder result = new StringBuilder();
    Map<Integer, String> map = new HashMap<>();
    int startIndex = 0;  //关键字起始索引
    int endIndex = 0;  //关键字结尾索引
    boolean isOpen = false;  //进入关键字匹配标志
    for (int i = 0; i < content.length(); i++) {  //遍历原始字符串
      for (char keyChar : keyword.toCharArray()) {  //遍历关键字字符串
        if (Character.toLowerCase(content.charAt(i)) == Character.toLowerCase(keyChar)) {
          if (!isOpen) {  //匹配到关键字第一个字符相等后
            startIndex = i;  //将起始索引赋值为当前遍历原始字符串索引
            endIndex = i;  //将结尾索引也赋值为相同到当前索引
            isOpen = true;  //标记进入匹配模式
          }
          //判断是否处于匹配模式
          endIndex++;    //将结尾索引自增
          i = endIndex;    //将遍历原始字符串到索引定位到结尾索引，避免重复遍历
        } else {
          isOpen = false;    //如果不相等则结束匹配模式
        }
      }
      if (endIndex - startIndex == keyword.length()) {  //如果结束索引与起始索引相减到值为关键字到长度则表明匹配到完整到关键字
        //将起始索引和结束索引对应到高亮标签put到哈希表中，并且重置匹配标识
        map.put(startIndex, "<font style='color:red'>");
        map.put(endIndex, "</font>");
        isOpen = false;

      }
    }
    //遍历原始字符串，通过哈希表中存储到高亮索引，将标签拼接到原始字符串里面
    for (int i = 0; i < content.length(); i++) {
      result.append(map.getOrDefault(i, "")).append(content.charAt(i));
    }
    //下面这一行是用来处理特殊情况，即关键字在最后到情况
    result.append(map.getOrDefault(content.length(), ""));
    return result.toString();
  }

  @Override
  public String getAboutPage() {
    DevcatNote one = getOne(new QueryWrapper<DevcatNote>().eq("view_type", ViewTypeEnum.ABOUT.getType()));
    if (one != null) {
      return textService.getNoteText(one.getId());
    }
    return null;
  }

  @Override
  public DevcatNote getNoteById(Long id) {
    return noteMapper.getNoteById(id);
  }

  @Override
  public PageData<DevcatNote> getNotePageDataForAdmin(SearchCommonParam param) {
    PageHelperUtil.handle(param);
    List<DevcatNote> devcatNoteList = noteMapper.getDevcatNoteList(param, null);
    return PageHelperUtil.makePageData(new PageInfo<>(devcatNoteList));
  }

  private void checkNOteParam(DevcatNote note) {
//    if(StringUtils.isEmpty(note.getNoteDescribe())){
//      throw new RuntimeException("请填写笔记描述");
//    }
    QueryWrapper<DevcatNote> wrapper = new QueryWrapper<>();
    if (note.getId() != null) {
      wrapper.eq("id", note.getId());
    }
    wrapper.eq("note_title", note.getNoteTitle());
    long count = count(wrapper);
    if (count > 0) {
      throw new RuntimeException("已经存在相同标题的笔记，创建失败");
    }
  }
}
